#include "FreeRTOS.h"
#include "queue.h"

#include "stm32f411_task_key.h"
#include "main.h"

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

#define KEY_RESULT_QUEUE_SIZE 10
#define KEY_EVENT_QUEUE_SIZE 10

static QueueHandle_t g_key_event_queue;
QueueHandle_t g_key_result_queue;

//申明函数
void key_init(void);
void key_task(void);

//初始化结构体
struct KeyInterface key_interface = {
    .pfinit = key_init,
    .pftask = key_task,
};


void key_init(void){
    g_key_event_queue = xQueueCreate(KEY_EVENT_QUEUE_SIZE, sizeof(key_event_t));
    g_key_result_queue = xQueueCreate(KEY_EVENT_QUEUE_SIZE, sizeof(key_result_t));
};

void key_task(void){
    key_result_t result;
    key_event_t* event;
    static uint32_t press_time;
    xQueueReceive(g_key_event_queue, &event, 0);
    if(event->state == KEY_PRESS)
    {
        press_time = event->triggle_tick;
    }else if(event->state == KEY_RELEASE)
    {
        press_time = event->triggle_tick - press_time;
        if(press_time < 50)
        {   
            //抖动
        }else if (50 < press_time && press_time < 1000)
        {
            //短按
            result = KEY_SHORT_PRESS;
            xQueueSendToBack(g_key_result_queue, &result, 0);

        }else
        {
            //长按
            result = KEY_LONG_PRESS;
            xQueueSendToBack(g_key_result_queue, &result, 0);
        }        
    }
    
};

//通过中断触发，组装key_event消息发送队列，并切换触发方式
key_event_t* key_msg;
key_event_t event;
void GPIO_Triggle_set(key_state_t key_state)
{
    
    if (key_state != event.state)
    {
        //组装事件消息
        event.state = key_state;
        event.triggle_tick = HAL_GetTick();

        //设置跳变沿切换
        GPIO_InitTypeDef GPIO_InitStruct = {0};
        if(KEY_RELEASE == event.state)
        {
            GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
        }
        else if(KEY_PRESS == event.state)
        {
            GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
        }
        else
        {   
        }
        GPIO_InitStruct.Pin = KEY_Pin;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(KEY_GPIO_Port, &GPIO_InitStruct);


        //发送key事件到队列
        key_msg = &event;
        xQueueSendFromISR(g_key_event_queue, &key_msg, NULL);
    }
}

//外部中断回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == KEY_Pin)
    {
        if(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin))
        {
            GPIO_Triggle_set(KEY_RELEASE);
        }
        else
        {
            GPIO_Triggle_set(KEY_PRESS);
        }
        
    }
}

